This is my first time working with objectBox. I have unfortunately stumbled on this issue and I failed to solve it.
I have two entities Product and Order as below.
#Entity()
class Customer{
int id;
String name;
#Backlink()
final orders = ToMany<Order>();
Customer({
this.id = 0,
required this.name,
});
}
#Entity()
class Order{
int id;
String? orderNumber;
final customer = ToOne<Customer>();
Order({
this.id = 0,
this.orderNumber,
});
}
A customer can place many orders but an order can only be placed by one customer.
I believe a list of all the orders for a specific customer can be returned simply by;
customer.orders;
But I would like to return a stream of all the orders made by a specific customer to feed into a streamBuilder. something like Stream<List<Order>>.
I have tried to read through the objectBox docs and I see I have to do something with backlink but I have failed to make it work. I would be very greatful for any help here.
Try to create and watch a link query, e.g. something like
final builder = store.box<Order>().query()
builder.link(Order_.customer, Customer.id.equals(customerId));
Stream<Query<Order>> ordersByCustomer = builder.watch();
Source/Details: https://docs.objectbox.io/queries#add-query-conditions-for-related-entities-links
Related
My app have String ID for all entities (Server side) I want migrate from Hive to Isar so I was reading the Isar documentation and find out it doesn't support String ID (only int), Yes I know that I can create a Class like this:
#Collection()
class Student {
int? id;
#Index(unique: true)
String? myServerId;
late String name;
final teacher = IsarLink<Teacher>();
}
When I fetch data (JSON) from server the id field (manager for Isar) don't came from server, so I save this record local Isar will create the ID OK, next time I get the same record from server is needed check via myServerId and if exist just update with id created by Isar its easy, how I can manager its with all entities filds like teacher? Need check every entities child or have a better way? Thanks in advance
set replace to true in #Index of myServerId,
like this:
#Collection()
class Student {
int? id;
#Index(unique: true , replace:true)
String? myServerId;
late String name;
final teacher = IsarLink<Teacher>();
}
check this Isar Replace indexes Doc.
I have a transaction class which stores the each transaction of a customer,Following are the fields in this class.
class Transaction{
#Id
private String id;
private Date date;
private String customerId;
private double openBalance;
private double transctionAmount;
private double finalAmount;
}
I need to fetch only the last inserted record of a customer (let say for customerId = cust123).
I defined following function in repository.
public interface TranscationRepository extends MongoRepository<Transaction, String> {
Optional<Transaction> findTopByCustomerIdOrderByIdDesc(String id);
}
This method giving last entry not by customerId but overall. I tried few modifications to it but did not get success.
I know I can findAllByCustomer but I don't want to pull huge list of transaction which is of no use in this use case. What is correct signature in spring mongo to get last inserted record by a field? I am ok to use custom #Query also.
Thank you.
Hi, I have the relationship table / model like the picture above.
A Teacher can take multiple trainings. A Training/Course can be a FormalTraining or not.
A Teacher may have many students.
Now I want to get list of Students whose teacher has taken a Course where IsFormalTraining == true.
How do I do that in .NET EF Core 2.2 ?
Edited:
models:
Teacher
{
int Id;
string Name;
ICollection<TeacherStudent> students ;
}
TeacherStudent{
int Id;
int TeacherId;
int StudentId;
}
Student {
int Id;
string Name;
}
TeacherTraining{
int Id;
int TeacherId;
int CourseId;
DateTime StartDate;
}
Course {
int Id;
string Name;
}
I'm making a few assumptions based on your classes so you might need to test and tweak, but I imagine it'll look something like this:
var students =
context.Students.Where(s =>
context.Teachers.Any(t =>
t.Students.Any(st => st.StudentId == s.Id) && context.TeacherTraining.Any(tt =>
tt.TeacherId == t.Id &&
context.Course.Any(c => tt.CourseId == c.Id && c.IsFormalTraining))));
I'm not able to debug this without rigging up a ton of stuff, so you might have to step through it. You could also break this up into more queries, it'll be easy to read and etc, but it probably won't be very efficient (granted, I don't know how efficient this is without running a test).
I'm new to Mongodb coming from relational databases and I'd also like to point out I'm using SpringBoot with JPA. If I were to build an automotive classified site where I would have thousands of Users and 100s of thousands of listings, how would I go about setting up the schema? I've read some articles that say normalizing nosql data is bad practices.
Anyhow lets say we have the following structure.
User
id
name
email
Cars
id
make
model
year
I would need to be able to list many cars with the User and what i've seen in my examples is it creates a nested array of cars within User. This would work great for user accounts where I'd like to provide the user with all their cars
Where I get a bit confused is with the cars. The cars need to be able to be searched very quickly and would not need the user info right away. In a sql db I would typically do a search against the cars (year, make, model) and grab the user later on if I needed it.
In mongodb, do you create a User document that contains a nested car array? or do you somehow create 2 documents that are both automatically maintained and search against the car document for performance reasons?
Sample code
#Document(collection = "person")
public class Person {
#Id
private String id;
private String firstName;
private String lastName;
// #DBRef(lazy = true)
private List<Listing> listings;
public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
#Document(collection = "listing")
public class Listing {
#Id
public String id;
public String year;
public String make;
public String model;
public String trim;
public Listing(String year, String make, String model, String trim) {
this.year = year;
this.make = make;
this.model = model;
this.trim = trim;
}
}
#Override
public void run(String... args) throws Exception {
repository.deleteAll();
List<Listing> listings = new ArrayList<>();
Listing listing = new Listing("2008", "Ford", "Focus", "SE");
//listingRepository.save(listing);
listings.add(listing);
Person person = new Person("Alice", "Smith");
person.setListings(listings);
// save a couple of customers
repository.save(person);
person = new Person("Bob", "Smith");
listings = new ArrayList<>();
listings.add(new Listing("2018", "Chrysler", "300", "S"));
person.setListings(listings);
repository.save(person);
// fetch all customers
System.out.println("Customers found with findAll():");
System.out.println("-------------------------------");
for (Person _person : repository.findAll()) {
System.out.println(_person);
}
System.out.println();
// fetch an individual customer
System.out.println("Person found with findByFirstName('Alice'):");
System.out.println("--------------------------------");
System.out.println(repository.findByFirstName("Alice"));
System.out.println("Persons found with findByLastName('Smith'):");
System.out.println("--------------------------------");
for (Person _person : repository.findByLastName("Smith")) {
System.out.println(_person);
}
List<Listing> _listings = listingRepository.findAll();
System.out.println("listings " + _listings.size());
_listings.forEach(v -> {
System.out.println(v.toString());
});
}
Going by your entity model,I think what you are looking for is analogous to Many to Many/One to Many relationship in a relational database. So you can go for One way Embedding or Two way Embedding in MongoDb.
For One way embedding, You can create a Car collection like below:
db.carCollection.insertMany([{
_id:1,
make: 'porcha',
model:'qwerty',
year:'2018'
},
{
_id:2,
make: 'ferrara',
model:'uiop',
year:'2018'
}])
You can then go on to create user collection as below:
db.userCollection.insert({
_id:1,
user:'Tom',
email:'tom#tom.com',
car_ids:[1,2]
})
The car_ids is an array which will hold the ids of cars that belong to the user.
You can fetch the cars belonging to an user as(using findOne to fetch the user. Search parameter should be an unique id. I am considering email to be unique here.Ideally it should be user's id) :
var user=db.userCollection.findOne({email:'tom#tom.com'})
db.carCollection.find({_id:{$in:user.car_ids}})
This will fetch you all the cars per user
For fetching cars only you can simply do:
db.carCollection.find({})
For Two way embedding you can have similar array (as in user collection) inside cars collection so that each car can be identified to its user.
I am working with Spring MongoDb.
I create various entities using insert method:
http://docs.spring.io/spring-data/mongodb/docs/current/api/org/springframework/data/mongodb/core/MongoOperations.html#insert-java.lang.Object-
However, all methods return void. I need to return the ObjectId of the inserted document.
What is the best way to get it?
This is pretty interesting and thought I would share. I just figured out the solution for this with the help of BatScream comment above:
You would create an object and insert it into your MongoDB:
Animal animal = new Animal();
animal.setName(name);
animal.setCat(cat);
mongoTemplate.insert(animal);
Your animal class looks like this with getters and settings for all fields:
public class Animal {
#Id
#JsonProperty
private String id;
#JsonProperty
private String name;
#JsonProperty
private String cat;
public String getId() {
return id;
}
}
AFTER you have done the insert under mongoTemplate.insert(animal);, you can actually call the method animal.getId() and it will return back the ObjectId that was created.
I had the same problem with #AlanH that animal.getId() is null. And then I just realized my id field had been set as a final field with a wither method. So of course getId() is null since the id field is immutable and the wither method returns a new object with id.
if this is the case: use animal = template.insert(animal).