ArangoDB Query with multiple OR? - arangodb

I am using the ArangoDB java driver and am trying to query for documents containing one of a number of Strings, which are stored in the arangoDB documents in lists. I am using ArrayList with a list of Strings in the query.
Query:
FOR document IN documents FILTER ( #now - document.dateAdded < 2592000000 ) &&
(document.categories IN #categories || document.tags IN #tags
|| document.locations IN #locations ) RETURN document
Map<String, Object> bindVars = new MapBuilder().put("now", now).put("categories", categories).put("#tags", tags).put("#locations", locations).get();
"now" contains a long. All the others are ArrayList<String>. This is throwing an error explaining that "bind parameter '#tags' has an invalid value or type". Since this ArrayList is no different than the others, my only theory is that I am inputting the logic incorrectly. How does one query for:
FunctionCondition1 AND (condition2 OR condition3 OR condition4)

The bind vars are marked in the query using '#', but they are given without the first '#'. A collection parameter is specified with two at symbols ## as ##myvariablecollection. In this case the bind var is #myvariablecollection and must be of type collection.
For example:
FOR a IN ##collection FILTER a.x == #now RETURN a
requires the bind variables to be given as #collection and now where #collection must name a collection and now should be (in this example) a number.
Map<String, Object> bindVars = new MapBuilder().put("#collection", "myCollection").put("now", 1234).get();

Related

How to find the string from string array in firestore

I have a list of documents and each document has a field of a string array named "fav", it has more than 50k emails, there are almost 1000 documents and in each document's "fav" array has variable length including 50k, 20k,10, etc. I was fetching all documents
Firestore.instance.collection("save").snapshots();
through StreamBuilder
StreamBuilder(
stream: Firestore.instance.collection("save").snapshots();,
builder: (context, snapshot) {
if (!snapshot.hasData)
return Text("Loading Data.............");
else {
listdata = snapshot.data.documents;
return _buildBody(snapshot.data.documents);
}
},
)
Now How I can search my required email from each document's field "fav"? I have to perform an operation after finding the required id in the array locally.
The question is not very clear, but for my understanding, this is what you are looking for
Firestore.instance.collection('save')
.where('fav', arrayContains: 'abc#gmail.com').snapshots()
The question is not very clear, but for my understanding, you want to find one e-mail in the array field. This array is contained on each document, and all the documents are "streamed" in a collection of snapshots.
Contains Method: https://api.dartlang.org/stable/2.0.0/dart-core/Iterable/contains.html
bool contains (
Object element
)
Returns true if the collection contains an element equal to element.
This operation will check each element in order for being equal to element, unless it has a more efficient way to find an element equal to element.
The equality used to determine whether element is equal to an element of the iterable defaults to the Object.== of the element.
Some types of iterable may have a different equality used for its elements. For example, a Set may have a custom equality (see Set.identity) that its contains uses. Likewise the Iterable returned by a Map.keys call should use the same equality that the Map uses for keys.
Implementation
bool contains(Object element) {
for (E e in this) {
if (e == element) return true;
}
return false;
}

Can I filter multiple collections?

I want to filter multiple collections, to return only documents who have those requirements, the problem is when there is more than one matching value in one collection, the elements shown are repeated.
FOR TurmaA IN TurmaA
FOR TurmaB IN TurmaB
FILTER TurmaA.Disciplinas.Mat >10
FILTER TurmaB.Disciplinas.Mat >10
RETURN {TurmaA,TurmaB}
Screenshot of the problem
What your query does is to iterate over all documents of the first collection, and for each record it iterates over the second collection. The applied filters reduce the number of results, but this is not how you should go about it as it is highly inefficient.
Do you actually want to return the union of the matches from both collections?
(SELECT ... UNION SELECT ... in SQL).
What you get with your current approach are all possible combinations of the documents from both collections. I believe what you want is:
LET a = (FOR t IN TurmaA FILTER t.Disciplinas.Mat > 10 RETURN t)
LET b = (FOR t IN TurmaB FILTER t.Disciplinas.Mat > 10 RETURN t)
FOR doc IN UNION(a, b)
RETURN doc
Both collections are filtered individually in sub-queries, then the results are combined and returned.
Another solution would be to store all documents in one collection Turma and have another attribute e.g. Type with a value of "A" or "B". Then the query would be as simple as:
FOR t IN Turma
FILTER t.Disciplinas.Mat > 10
RETURN t
If you want to return TurmaA documents only, you would do:
FOR t IN Turma
FILTER t.Disciplinas.Mat > 10 AND t.Type == "A"
RETURN t
BTW. I recommend to call variables different from collection names, e.g. t instead of Turma if there is a collection Turma.

How to bind variables inside collection literals in Cassandra 3.0 using java?

I have a java application in which I am parsing data and updating it to my Cassandra 3.0 database. I have been successful so far until it comes to my columns with user-defined types.
My attempt:
String statement_update = "UPDATE table SET "
+ "elements = elements + [{name: ? , associations: []}]"
+ " WHERE id = ?
elements is a user defined type in my Cassandra 3.0 Database.
It is composed of name (data type: text) and associations (data type: list).
PreparedStatement prepared_update = session.prepare(statement_update);
bound_update = prepared_update.bind(name, id);
variables name and id are of type String.
I have been trying to use a prepared statement to update my table with newly parsed data; however after the data is parsed I am having trouble adding more elements to my elements column. I get error: “Invalid list literal for elements: bind variables are not supported inside collection literals.” How do I work around or resolve this?
I have tried ways of changing the statement_update to “UPDATE table SET elements = elements + ? WHERE id = ?”, but I don’t know what kind of list (or even if its a list) to add to my bind statement.
What is needed to satisfy my user-defined type: elements?
Try another update notation:
session := getGocqlSession()
err := session.Query(
"UPDATE table SET mymapcolumn[?] = ? WHERE rowkey = ?",
mapKey, mapValue, rowKey,
).Exec()
This worked for me.
I have done this on Go, but maybe this approach will help.

Sorting DAM asset and Cq page based on last modified

I am trying to perform a freetext search on all the Cq:Page and dam:Asset with the ordering being the last modified.
I have created the Query for search which is as below:
1_group.p.or=true
1_group.1_type=cq:Page
1_group.2_type=dam:Asset
2_group.p.or=true
2_group.1_path=/content
2_group.2_path=/content/dam
fulltext=text
p.limit=-1
Now I need to sort the results based on last modified. But since cq:Page has property jcr:content/cq:lastModified and dam:Asset has property jcr:content/jcr:lastModified, I am unable to figure out which property should i use in the orderby field of predicate. Is there any way to form a predicate which uses different property values for pages and assets during sorting. Please let me know if we can achieve this in a single query.
Regards,
Shailesh
This can be done by creating a custom AbstractPredicateEvaluator and overriding the getOrderByComparator with your own comparator. Then you would register your custom predicate evaluator for your Query by calling registerPredicateEvaluator.
In the example below, you can use whatever you'd like for the customSort.sortby property. This can be useful if your comparator handles multiple types of sorting. You can get this information from the predicate via predicate.get("sortby").
QueryBuilder builder = resourceResolver.adaptTo(QueryBuilder.class);
Map<String, String> params = new HashMap<String, String>();
params.put("1_group", "true");
params.put("1_group.1_type", "cq:Page");
params.put("1_group.2_type", "dam:Asset");
params.put("2_group.p.or", "true");
params.put("2_group.1_path", "/content");
params.put("2_group.2_path", "/content/dam");
params.put("fulltext", text);
params.put("p.limit", "-1");
params.put("customSort.sortby", "last-modified");
PredicateGroup pg = PredicateGroup.create(params);
Query query = builder.createQuery(pg, resourceResolver.adaptTo(Session.class));
query.registerPredicateEvaluator("customSort", new CustomSortPredicateEvaluator());
SearchResult result = query.getResult();
there is no way since they are differenet type (cq:lastModified & jcr:lastModified), Even you use SQL2 like this (SELECT p.* FROM [nt:base] AS p WHERE ISDESCENDANTNODE(p, '/content') AND ( p.[jcr:primaryType]='dam:Asset' OR p.[jcr:primaryType]='cq:Page')) there no way to use ORDER BY.
Have to use Java code for sorting.
Keep your Query, get QueryResult to List and do Comparator Sort

Mongo DB C# code using 2 level , 3 level and 4 level of array

I have to update in C# code using MongoDB. Here I had implement 2nd level array of update in below (subBranchindex is taken in a generic list object):-
for (var index = 0; index < subBranchindex.Count; index++)
{
if (subBranchindex[index]._id == new ObjectId(subBranchid))
{
IMongoQuery queryEdit = Query.EQ("BranchOffice.SubBranchlist._id", new ObjectId(subBranchid));
UpdateBuilder update = Update.Set("BranchOffice.$.SubBranchlist."+ index +".Name",subBranch.SubName).
SafeModeResult s = dc.Collection.Update(queryEdit, update,
UpdateFlags.None, SafeMode.True);
}
}
Here 2nd level array, I was using (for loop Statement) to taken Index value for array. Next I can use 3rd, 4th and 5th level of array means more than (for loop statement) will be assign. So don't need [for loop Statement] and also don't need to assign hardcore number in index.
For example: ("BranchOffice.$.SubBranchlist.0.Name",subBranch.SubName). Here Don't Hardcore number[index] 0 or 1 or 2. "2nd" level array more than 100 record is there.
Is there any way I can use to array index value? Please explain how to solve this probelm. Please explain me with Example.
Based on your example above, my understanding of your schema is the following:
The top-level document has a BranchOffice field
BranchOffice is an array of objects
Each object within BranchOffice has an _id, SubName and SubBranchlist field
SubBranchlist is an array of objects
Each object within SubBranchlist has a Name field
Your update statement appears to be copying the SubName field to each Name field among objects within SubBranchlist (a sibling field of SubName).
Using the property path syntax to select fields through arrays (e.g. SubBranchlist.0.Name), there is no "wildcard" index that will allow you to modify Name fields among all objects in the array.
On a somewhat related note, the $ positional operator only applies to the first-matched array element, so you cannot use that to update multiple array elements. In your case, it would not be an option anyway, since you're using the positional operator for the BranchOffice array field.
You can either issue a series of update queries (for each element in SubBranchlist), or consider using $set to modify the entire SubBranchlist array in one query. The downside with using $set is that you'll need to read and write back the entire array, which may be a problem if other, concurrent operations are also issuing updates to the array.

Resources