How to filter by count on gremlin map (OrientDB) - orientdb

I have a somewhat similar business problem to - Gremlin filter by count
, but I'm running on OrientDB 3.0.16
This query:
g.V().hasLabel('skill').
groupCount()
Returns from OrientDB, as expected:
{
"result": [
{
"com": 1,
"netcompactframework": 1,
"netremoting": 2,
"netframework": 3,
"net": 1,
"netclr": 1
}
],
"elapsedMs": 18
}
I tried to apply an unfold and where filter after it:
g.V().hasLabel('skill').
groupCount().
unfold().
where(select(values).is(gt(1)))
But I get an error:
{
"errors": [
{
"reason": 501,
"code": 501,
"content": "java.lang.UnsupportedOperationException: Cannot convert netremoting=2 - class java.util.HashMap$Node to JSON"
}
]
}
It seems that problem is with unfold() as OrientDB is trying to convert the map entry string into JSON and fails
Any ideas?
Is this an OrientDB specific issue? Maybe there is another way to perform the same logic in gremlin?

That looks like a serialization error of some sort, but I'm not sure of the circumstance under which you are operating to get that problem. When you unfold() a Map, it gets converted to Java Map.Entry and returning that seems to be a problem for the serializer which along the way encounters the internal class HashMap$Node. I think you can work around this problem by folding back to a Map:
g.V().hasLabel('skill').
groupCount().
unfold().
where(select(values).is(gt(1))).
group().
by(keys).
by(select(values))
I would be curious to know what circumstances cause you to get that error. Standard GraphSON serializers in Gremlin Server should be able to handle HashMap$Node so it's curious that you'd be getting this problem at all.

Related

Mongo Scala Driver: PullByFilter Based on Nested Field Value

I have a model band that contains a list of tours
Band:
{
name: String,
email: String,
createdAt: String,
tours: Tour[],
...
}
where a Tour is:
{
name: String,
region: String,
published: Boolean,
...
}
The goal is simply to create an end point that receives a Band Name and Tour Name deletes a tour based on this input.
The following works:
bandService.getBandByName(req.getParam("bandName")).flatMap{ b =>
val tour = b.tours.filter(t => t.name == req.getParam("tourName")).head
mongoDataBaseConnector.bands.findOneAndUpdate(
equal("bandName", req.getParam("bandName")),
pull("tours", tour)
).toFuture().flatMap(u => bandService.getBandByName(req.getParam("bandName")))
However, this requires me to first resolve the band by the name received first, filter, find the tour and pass in the exact object in to the pull I am trying to avoid this by using pullByFilter but can't seem to get this to work. Unfortunately couldn't find any examples of this function in the scala driver.
This is what I am trying:
mongoDataBaseConnector.bands.findOneAndUpdate(
and(
equal("bandName", req.getParam("bandName")),
equal("tours.name", req.getParam("tourName"))),
pullByFilter(and(
equal("tours.$.name", req.getParam("tourName")),
equal("tours.$.region", req.getParam("region"))
))
).toFuture().flatMap(u => bandService.getBandByName(req.getParam("bandName")))
this gives the following error:
com.mongodb.MongoCommandException: Command failed with error 2 (BadValue): 'Cannot apply $pull to a non-array value' on server cluster0-shard-00-01-sqs4t.mongodb.net:27017. The full response is {"operationTime": {"$timestamp": {"t": 1568589476, "i": 8}}, "ok": 0.0, "errmsg": "Cannot apply $pull to a non-array value", "code": 2, "codeName": "BadValue", "$clusterTime": {"clusterTime": {"$timestamp": {"t": 1568589476, "i": 8}}, "signature": {"hash": {"$binary": "Qz/DqAdG11H8KRkW8gtvRAAE61Q=", "$type": "00"}, "keyId": {"$numberLong": "6710077417139994625"}}}}
Any ideas are appreciated. Is this even possible with this function?
Okay, I've been working on a nearly identical problem all day. What I have isn't great, but it's enough that I'm willing to accept it and hopefully someone will be able to make it into a more fully-formed solution. Or at least I can save someone else some time.
pullByFilter only accepts one argument. It seems that argument can be another Bson filter which is applied directly to each of the children, or a BsonValue that will be matched against. Since none of the Bson filters step into the child documents, you have to create a BsonValue, specifically, a document. I believe this should solve your problem:
mongoDataBaseConnector.bands.findOneAndUpdate(
and(
equal("bandName", req.getParam("bandName")),
equal("tours.name", req.getParam("tourName"))),
pullByFilter(BsonDocument().append("tours", BsonDocument()
.append("name", req.getParam("tourName"))
.append("region", req.getParam("region"))
))
).toFuture().flatMap(u => bandService.getBandByName(req.getParam("bandName")))
I would have liked to be able to switch back using Bson filters after getting to the inner document, but it seems that once you're in BsonValues, you can't go back.
Edit: To help whoever comes after me: I think there should be a way to solve this more cleanly with arrayFilters, but I haven't yet found it.

Azure CosmosDB operation not supported when using $elemMatch and $in

I am doing a query like the following, which works fine with MongoDB, but sometimes fails with CosmosDB. I need it to work with both.
(XXX is a placeholder for any string value. All strings have unique values that are redacted for readability, and actual content should be of no significance.)
{
server_index: {
$elemMatch: {
server: "XXX",
index: "XXX",
delete_time: { $exists: false },
path: {
$in: ["XXX", "XXX", "XXX" ]
}
}
}
}
The schema of a document is somewhat like this:
{
...,
server_index: [
{
server: "XXX",
index: "XXX",
delete_time: ISODate(...), // optional
path: "XXX"
},
{...}, // same as above
...
],
...
}
This query sometimes works as expected with CosmosDB as well, but sometimes I also get the following response:
{
_t: "OKMongoResponse",
ok: 0,
code: 115,
errmsg: "Command is not supported",
$err: "Command is not supported"
}
What is especially strange is that the query seemingly succeeds, and the response above is returned by a "valid" cursor as the first document, which then causes my document parser "crash".
I am using the C++ legacy driver. Is this even supported by Cosmos DB?
(According to the developer I inherited this project from, it is, and as always when you inherit projects, it all worked fine according to the previous developer... So this may be due to a change in Cosmos DB, due to the nature of my test data, or who knows what...)
Side note: In MongoDB, there is a multi-key index on server_index, which looks like this:
{
"server_index.delete_time" : 1,
"server_index.server" : 1,
"server_index.index" : 1,
"server_index.path" : 1
}
Is this even supported in CosmosDB?
EDIT: Trying to add this index with Robo 3T silently fails, with no error message whatsoever. The index is simply not added. Nice!
(Please don't ask about the strange database schema. It is like it is for a reason, and believe me, I, too, would like to burn it all down and replace it with something else ... I am open for suggestions for alternative queries, though)
This was probably a server-side problem. It seemed wrong in the first place (error status returned as part of the query result), and it has disappeared after a couple of weeks without me changing anything.

API $expand and &count

Is it possible to use $expand but instead of returning a collection of objects, just return the count of objects?
For example, get an account and a count of its annotations in a single WebApi call
I've tried a few things.
Obvious attempt: accounts(6CDEEB72-2AC8-E711-A825-000D3AE0A7F8)?$select=name&$expand=Account_Annotation($count=true) returns all fields of all Annotations but doesn't count anything.
Next I tried accounts(6CDEEB72-2AC8-E711-A825-000D3AE0A7F8)?$select=name&$expand=Account_Annotation($select=annotationid&$count=true) returns an error: "Found an unbalanced bracket expression". I think this is related to the & symbol in the $expand
I found a non-crm blog that said this could be resolved with a ; but when I tried accounts(6CDEEB72-2AC8-E711-A825-000D3AE0A7F8)?$select=name&$expand=Account_Annotation($select=annotationid;$count=true) it doesn't give an error, but the $count instruction seems to be ignored
A crazy attempt of accounts(6CDEEB72-2AC8-E711-A825-000D3AE0A7F8)?$select=name&$count=Account_Annotation($select=annotationid) returns a "not a valid count" error
I'm guessing that this is not a valid combination, but I thought I would post here in case someone else has achieved this successfully.
I got this working, but I'm not sure it's what you are looking for exactly, it only works if I put the count before expand:
api/data/v9.0/cmnt_salesexample?
$select=endcustomeraccountid&$count=true&$expand=endcustomerid($select=accountid)
output:
{
"#odata.context": "https://xyz",
"#odata.count": 5000,
"value": [
{
"#odata.etag": "W/\"3560581422\"",
"endcustomerid": "54321"
},
{
"#odata.etag": "W/\"3510396844\"",
"endcustomerid": "12345"
},
...

how to get term vectors by using Elasticsearch Hadoop

I'm using ElasticSearch-Hadoop API. And I was trying to get _mtermvector by using the following Spark code:
val query= """_mtermvectors {
"ids" : ["1256"],
"parameters": {
"fields": [
"tname"
],
"term_statistics": true
}
}"""
var idRdd = sparkContext.esRDD("uindex/type1",query)
It didn't work, any ideas please, appreciate!
You can't use endpoints (like _mtermvectors) which are part of the document API's with ES-Hadoop. Only queries which belongs to the query API's, query DSL or external resource are allowed.
Hope that it helps.

How to query Cloudant documents for a specific field

I am new to Cloudant and I need to do a simple query on a specific document field. My documents have the following structure and I need to get only the documents with status=SIGNED
{
"_id": "3ddb4058f3b24a7a9c585f997e30ff78",
"_rev": "3-757c82c48f4e7c333911be6859aff74e",
"fileName": "Generali Architects",
"status": "SIGNED",
"user": "italy",
"_attachments": {
"Generali Architects": {
"content_type": "application/pdf",
"revpos": 3,
"digest": "md5-9hqSif7CzQ2yvKxSSbj+dw==",
"length": 323653,
"stub": true
}
}
}
Reading Cloudant documentation I created the following Design Document with a related view which returns exactly what I expected
Then from my Java application I use the following code
String cloudantView = "_design/signedDocs/status-signed-iew";
List<SignDocDocument> docs =
db.view(cloudantView).includeDocs(true).query(SignDocDocument.class);
which always returns me "org.lightcouch.NoDocumentException: Object Not Found"
Any idea which kind of mistake I am making here?
Thank you very much
Is it the typo in "_design/signedDocs/status-signed-iew"; e.g. that should be "_design/signedDocs/status-signed-view"; (depending on how your java library works...).
Always worth checking the view by direct access in your browser, too, just to make sure it's returning the expected data.