You can try aggregation.
Update the UsedIn
class below.
private Long carId; private CarDocument car; private Date usedDate; private String usedByUsername;
Mongo Shell Query:
db.tools.aggregate([{ "$match": { "madeInCountry": "germany" } }, { "$unwind": "$usedIn" }, { "$lookup": { "from": "cars", "localField": "usedIn.carId", "foreignField": "_id", "as": "usedIn.car" } }, { "$unwind": "$usedIn.car" }, { "$match": { "usedIn.car.madeInCountry": "germany" } }, { "$group": { _id: "$_id", usedIns: { "$push": "$usedIn" } } }])
Spring Aggregation Code:
Criteria toolQuery = Criteria.where("madeInCountry").in("germany"); MatchOperation toolMatchOperation = new MatchOperation(toolQuery); LookupOperation lookupOperation = LookupOperation.newLookup(). from("cars"). localField("usedIn.carId"). foreignField("_id"). as("usedIn.car"); Criteria carQuery = Criteria.where("usedIn.car.madeInCountry").is("germany"); MatchOperation carMatchOperation = new MatchOperation(carQuery); TypedAggregation<ToolDocument> aggregation = Aggregation.newAggregation(ToolDocument.class, toolMatchOperation, Aggregation.unwind("usedIn"), lookupOperation, Aggregation.unwind("usedIn.car"), carMatchOperation, Aggregation.group("id").push("usedIn").as("usedIn")); List<ToolDocument> results = mongoTemplate.aggregate(aggregation, ToolDocument.class).getMappedResults();
Ways to load data.
Vehicle Details
public void saveCar() { carDao.deleteAll(); CarDocument carDocument1 = new CarDocument(); carDocument1.setId(1L); carDocument1.setName("audi"); carDocument1.setMadeInCountry("germany"); carDao.save(carDocument1); }
Tool data
public void saveTool() { toolDao.deleteAll(); ToolDocument toolDocument1 = new ToolDocument(); toolDocument1.setId(1L); toolDocument1.setName("wrench"); toolDocument1.setMadeInCountry("germany"); UsedIn usedIn1 = new UsedIn(); usedIn1.setCarId(1L); usedIn1.setUsedByUsername("user"); usedIn1.setUsedDate(new Date()); List<UsedIn> usedIns1 = new ArrayList<>(); usedIns1.add(usedIn1); toolDocument1.setUsedIn(usedIns1); toolDao.save(toolDocument1); }
Update:
To answer the question about access to DBRefs
II. findTools by list of carDocuments and String.
I do not know what to call this dao with a list of CarDocuments and madeInCountry String?
public List<ToolDocument> findByMadeInCountryAndUsedInCarIn(String madeInCountry, List<CarDocument> carDocuments);
As I noted in the first comment, the second call you need is a call to the built-in dbref with a list of the cost of automotive documents. The request will search for a match and return all the documents of the car if a match is found for the tool document. This means that you will receive documentary documents that are made in Germany, which are at least used in a card document made in Germany.
Remaining Update ( $lookup
equalivent) (Idea taken from here by MongoDB for using Sharding with the $ lookup aggregation operator )
List<ToolDocument> toolDocuments = toolDao.findByMadeInCountry("germany"); List<Long> carIds = toolDocuments.stream().map(tool -> tool.getUsedIn().stream().map(UsedIn::getCarId).collect(Collectors.toList())).flatMap(List::stream).collect(Collectors.toList()); List<CarDocument> carDocuments = carDao.findByMadeInCountryAndIdIn("germany", carIds);