Camel / MongoDB - $in operator with reference to another collection/document array - java

I came across this blog post in looking for a way to organize relationships. What I'm getting confused on is the syntax behind the following statement. I realize by virtue of the javascript variables, the following is possible..
var party = {
_id: "chessparty",
name: "Chess Party!",
attendees: ["seanhess", "bob"]
}
var user = { _id: "seanhess", name: "Sean Hess", events: ["chessparty"]}
db.events.save(party)
db.users.save(user)
db.events.find({_id: {$in: user.events}}) // events for user
db.users.find({_id: {$in: party.attendees}}) // users for event
What is throwing me for a spin in the last two lines though, since what I'm trying to do is something like this in Java. So I understand the idea, but I want to accomplish this in Java, more specifically, the Camel/MongoDB component.
I've been referencing the following documentation and looking at the "findAll" operation. So would I need to first run a query to get the array, for example the "user.events" and then run a second query to find the list of events? Or is there a way to reference the field "events" in collection "db.user" as part of the query on "db.events"?
Something to the tune of the following with a single query..
pseudo idea: db.events.find({_id: {$in: [db.user.events]}})
Ultimately I'm looking to translate this into something like the following..
from("direct:findAll")
.setBody().constant("{ \"_id\": {$in :\"user.events\" }}")
.to("mongodb:myDb?database=sample&collection=events&operation=findAll")
.to("mock:resultFindAll");
I'm a bit new to the mongodb camel component, so I'm wondering if there are any gurus that have already been there done that sort of thing?? And have any advice on the subject. Or to find out without 2 days of trial and error that this simple isn't possible..?
Thanks!

I thought I'd wrap this question up, it has been some time now and a few weeks ago I was able to work past this.
Basically I would up storing an array of userId's in the events collection..
example:
{
_id : 22bjh2345j2k3v235,
eventName : "something",
eventDate : ISODate(...),
attendees : [
"abc123",
"def098",
"etc..."
]
}
essentially assigning users to events. This way I could find all events a user was participating in, and I wound up with a list of users per event.
if I wanted to find all events for a user:
from("direct:findAll")
.setBody().simple("{ \"attendees\": \"${header.userId}\" }")
.to("mongodb:myDb?database=sample&collection=events&operation=findAll")
.to("mock:resultFindAll");

Related

Spring Data MongoDb elemMatch criteria matching all search strings

I'm having an issue with custom Spring Data queries with MongoDb and Java. I'm attempting to implement a flexible search functionality against most of the fields of the document.
This document represents a person, and it contains a set of addresses embedded in it; the address has a field that is a set of strings that are the 'street address lines'.
I started with Query By Example, and this works for the single fields. but doesn't work for other types - such as this set of strings. For these, I'm building custom criteria.
The search criteria includes a set of street lines that I would like to match against the document's lines. If every line in the search is found in the document, the criteria should be considered matching.
I've tried using elemMatch, but this doesn't quite work like I want:
addressCriteriaList.add(Criteria.where("streetAddressLines").elemMatch(new Criteria().in(addressSearch.getStreetAddressLines())));
This seems to match if only ONE line in the document matches the search. If I have the following document:
"streetAddressLines": [ "123 Main Street", "Apt 1" ]
and the search looks like this:
"streetAddressLines": [ "123 Main Street", "Apt 2" ]
the elemMatch succeeds, but that's not what i want.
I've also tried looping through each of the search lines, trying an elemMatch to see if each is in the document:
var addressLinesCriteriaList = new Array<Criteria>();
var streetAddressLines = address.getStreetAddressLines();
streetAddressLines.forEach(l -> addressLinesCriteriaList.add(Criteria.where("streetAddressLines").elemMatch(new Criteria().is(l))))
var matchCriteria = new Criteria.andOperator(addressLinesCriteriaList);
This doesn't seem to work. I have done some experimenting, and it may be that this doesn't seem to work: new Criteria().is(l)
I tried this, and this DOES seem to work, but I would think that it's really inefficient to create a collection for each search line:
streetAddressLines.forEach(l ->
{
var list = new ArrayList<String>();
list.add(l);
addressCriteriaList.add(Criteria.where("streetAddressLines").elemMatch(new Criteria().in(l)));
});
So I don't know exactly what's going on - does anyone have any ideas of what I'm doing wrong? Thanks in advance.
You need to use the $all operator or the all method of Criteria class. Something along these lines:
addressCriteriaList.add(Criteria.where("streetAddressLines").all(addressSearch.getStreetAddressLines()));
If addressSearch.getStreetAddressLines returns a list, try this:
addressCriteriaList.add(Criteria.where("streetAddressLines").all(addressSearch.getStreetAddressLines().toArray(new String[0])));

How to search in firebase database

I'm trying to filter the data from my database using this code:
fdb.orderByChild("title").startAt(searchquery).endAt(searchquery+"\uf8ff").addValueEventListener(valuelistener2);
My database is like this:
"g12" : {
"Books" : {
"-Mi_He4vHXOuKHNL7yeU" : {
"title" : "Technical Sciences P1"
},
"-Mi_He50tUPTN9XDiVow" : {
"title" : "Life Sciences"
},
"-Mi_He51dhQfl3RAjysQ" : {
"title" : "Technical Sciences P2"
}}
While the code works, it only returns the first value that matches the query and doesn't fetch the rest of the data even though it matches.
If I put a "T" as my search query, I just get the first title "Technical Sciences P1 " and don't get the other one with P2
(Sorry for the vague and common question title, it's just I've been looking for a solution for so long)
While the codes works, it only returns the first value that matches the query
That's the expected behavior since Firebase Realtime Database does not support native indexing or search for text fields in database properties.
When you are using the following query:
fdb.orderByChild("title").startAt(searchquery).endAt(searchquery+"\uf8ff")
It means that you are trying to get all elements that start with searchquery. For example, if you have a title called "Don Quixote" and you search for "Don", your query will return the correct results. However, searching for "Quix" will yield no results.
You might consider downloading the entire node to search for fields client-side but this solution isn't practical at all. To enable full-text search of your Firebase Realtime Database data, I recommend you to use a third-party search service like Algolia or Elasticsearch.
If you consider at some point in time to try using Cloud Firestore, please see the following example:
Is it possible to use Algolia query in FirestoreRecyclerOptions?
To see how it works with Cloud Firestore but in the same way, you can use it with Firebase Realtime Database.

Count specific enum values with JPA rather than manually

I have a list of status enum values which I am currently iterating over and using a basic counter to store how many in my list have the specific value that I am looking for. I want to improve greatly on this however and think that there may be a way to use some kind of JPA query on a paging and sorting repository to accomplish the same thing.
My current version which isn't as optimized as I would like is as follows.
public enum MailStatus {
SENT("SENT"),
DELETED("DELETED"),
SENDING("SENDING"),
}
val mails = mailService.getAllMailForUser(userId).toMutableList()
mails.forEach { mail ->
if (mail.status === MailStatus.SENT) {
mailCounter++
}
}
With a paging and sorting JPA repository is there some way to query this instead and get a count of all mail that has a status of sent only?
I tried the following but seem to be getting everything rather than just the 'SENT' status.
fun countByUserIdAndMailStatusIn(userId: UUID, mailStatus: List<MailStatus>): Long

SugarCRM custom field

I'am writing a software for the data-synchronization of a custom software and sugarCRM. Therefore I need an updateOrCreate() function. My Problem is, that the custom software uses other uuid´s than sugarCRM so i can´t look for the uuid to check on update or create.So I want to save the custom-uuid in a custom field of sugarCRM.
But i have no idea how to do that over the REST-API of sugarCRM.
By the way I wrote a java-application.
Thank you for help!
As far as I'm aware there is no update-or-create API (see https://your-sugarsite/rest/v10/help), howewer if you just want to use the API (rather than customize it) you could sync data like this:
1) Fetch all ids of records that have a custom uuid by using the POST /rest/v10/<module>/filter endpoint and a payload similar to:
{
offset: 0,
max_num: 1000,
fields: ["id", "custom_uuid_c"],
filter: [{"custom_uuid_c": {"$not_empty": ""}}],
]
}
or if you just need a specific custom uuid at a time:
{
offset: 0,
max_num: 1000,
fields: ["id"],
filter: [{"custom_uuid_c": {"$equals": "example-custom-uuid"}}],
]
}
The response will look something like this:
{
next_offset: -1,
records: [
{"id": "example-sugar-uuid", "custom_uuid_c": "example-custom-uuid"},
...
],
}
Notes:
Make sure to evaluate next_offset as even with a high max_num you may not get all records at once because of server limits. As long as next_offset isn't -1 you should use its value as offset in a new request to get the remaining records.
You can supply all field names you need to sync in the fields array, so that you get that information early and can check whether or not an update is required at all (maybe data is still up-to-date?)
Sugar also always include certain fields in the response, no matter if they were requested or not. (E.g. id and date_modified). I did not include them all in the response snippets for the sake of simplicity.
2)
Based on the information received in the previous step you know which sugar ID belongs to which custom UUID and you can detect/prepare data for updates.
If you need to sync all and retrieve the complete list first, I suggest you create a lookup table custom-uuid => sugar-id, so that you do not have to loop through the data array and compare fields when looking for a specific number.Don't forget to consider the possibility of a custom-uuid being present in one than more Sugar-record at a time, unless you enforce them being unique on the server/database side.
3)
Now that you have all the information you need you can update and create records as needed:
Update existing record: PUT /rest/v10/<module>/<record_id>
Create missing record: POST /rest/v10/<module>
If want to send a lot of creates and/or updates in a single request, have a look at the POST /rest/v10/bulk API - if your version of Sugar has it.
Final notes:
The filter operators definition on /rest/v10/help seems incomplete, for more info you can check the filter docs

Finding a list of related objects by ID

Let's say for example I have a bridge table called PersonAnimal. I want to search for all the people who have a given animal's ID. The query so far looks like:
Animal animal = getById(Animal.class, animalId)
ObjectSelect
.query(PersonAnimal.class)
.where(PersonAnimal.ANIMAL.eq(animal))
.select(context)
However the first line in the above code segment shows that I first have to retrieve the related object from the database. I want to get rid of that database lookup and instead do something like:
ObjectSelect
.query(PersonAnimal.class)
.where(PersonAnimal.ANIMAL_ID.eq(animalId)) // <- Find by ID instead
.select(context)
Is that possible?
I am running version 4.1 of the Apache Cayenne ORM.
Just as I posted the question I found the answer. You need to create an Expression using a Property object like so:
val findByIdExpr = Property.create(PersonAnimal.ANIMAL.name, Long::class.java).eq(yourId)
val gotList = ObjectSelect
.query(PersonAnimal.class)
.where(findByIdExpr)
.select(context)
Above code is in Kotlin but is also easy to understand from a Java perspective.

Categories

Resources