Related
I want to add a field array to mongoDB in laravel. I use push to create an array field. And I did it the following way:
public function addFieldByUser($id)
{
$product = Product::find($id);
if (empty($product)) {
abort(404);
}
if (!isset($product->image['productC'])) {
$product->push("image.productC", []);
}
}
I have successfully added the field productC in mongoDB, and here are the results:
{
"_id" : ObjectId("6295eb7210b4ec7cb72c9426"),
"name" : "test",
"image" : {
"productA" : [
{
"_id" : "6295eb6c8e88fb54231e66c3",
"link" : "https://example.com",
"image" : "dc1c94e421d4ab6a592bcae33ec97345.jpg",
"externalLink" : true
}
],
"productB" : [
{
"_id" : "6295eb957cb6f9350f0f0de5",
"link" : "https://example.com",
"image" : "1ccd4b1d7601a3beb213eb5b42c5d9bf.jpg",
"externalLink" : true
}
],
"productC" : [
[]
]
}
}
But inside productC there is one more sub-array. But my original intention was to add field productC as an empty array
I would like to have a result like this:
{
"_id" : ObjectId("6295eb7210b4ec7cb72c9426"),
"name" : "test",
"image" : {
"productA" : [
{
"_id" : "6295eb6c8e88fb54231e66c3",
"link" : "https://example.com",
"image" : "dc1c94e421d4ab6a592bcae33ec97345.jpg",
"externalLink" : true
}
],
"productB" : [
{
"_id" : "6295eb957cb6f9350f0f0de5",
"link" : "https://example.com",
"image" : "1ccd4b1d7601a3beb213eb5b42c5d9bf.jpg",
"externalLink" : true
}
],
"productC" : []
}
}
Anyone please give me any suggestions, I'm new to mongoDB so it's really giving me a hard time. Thank you very much
Push doesn't make sense here. push implies that you have an array that you want to add a value to. But here you just want to initialise an array, so you'll have to use another method.
(Also notably if you use push on an eloquent model it'll also save it to the database)
You could do something like $product->image['productC'] = []
And then $product->save() if you want to save it
I created a simple project in Drools work bench. The project has 1 data object and 2 DRL files. I build and deployed the project to the KIE server. And I have created a simple spring boot application which loads data into the data object using a rest service and fires the rules. Below is the code:
public class Main {
private static String containerId = "ImportProducts_1.0.1-LATEST";
private static String user = "kieserver";
private static String password = "kieserver1!";
private static String url = "http://localhost:8180/kieserver/services/rest/server";
private static final Logger LOGGER = LoggerFactory.getLogger(Main.class);
private static final MarshallingFormat FORMAT = MarshallingFormat.JSON;
private static String CLASS_NAME = "ImportProduct";
public static void main(String[] args) {
List<ImportProduct> prods = new ArrayList<>();
prods.add(new ImportProduct("1", "Grocery - Milk", "OK", 25.0));
prods.add(new ImportProduct("2", "Fashion - Trouser", "NOT_OK", 1300.0));
prods.add(new ImportProduct("3", "Grocery - Wheat", "OK", 425.0));
prods.add(new ImportProduct("4", "Grocery - Dairy Milk Chocolate", "OK", 100.0));
KieServicesConfiguration config = KieServicesFactory.newRestConfiguration(url, user, password, 60000);
config.setMarshallingFormat(MarshallingFormat.JSON);
RuleServicesClient client = KieServicesFactory.newKieServicesClient(config).getServicesClient(RuleServicesClient.class);
List<Command<?>> cmds = new ArrayList<>();
KieCommands commands = KieServices.Factory.get().getCommands();
cmds.add(commands.newInsert(prods, CLASS_NAME));
cmds.add(commands.newFireAllRules());
BatchExecutionCommand myCommands = CommandFactory.newBatchExecution(cmds);
ServiceResponse<ExecutionResults> response = client.executeCommandsWithResults(containerId, myCommands);
if (response.getType() == ServiceResponse.ResponseType.SUCCESS) {
LOGGER.info("Commands executed with success! Response: ");
LOGGER.info("{}", response.getResult());
List<ImportProduct> prodUpdated = (List<ImportProduct>) response.getResult().getValue(CLASS_NAME);
//sale.setDiscount(saleUpdated.getDiscount());
LOGGER.info("Response is: {}", response.getMsg());
LOGGER.info("Output is: {}", prodUpdated.toString());
} else {
LOGGER.error("Error executing rules. Message: {}", response.getMsg());
}
//KieServices kieServices = KieServices.Factory.get();
//ReleaseId releaseId = (ReleaseId) kieServices.newReleaseId( "com.test", "ImportProducts", "1.0.1-LATEST" );
}
}
The application runs without errors but the there is no impact of the rules on the data fed in the KIE container. The rule deletes the data object if the status != 'OK'. I am getting all the data back I sent in the request body of the POST request service. I think DRL capability is enabled as shown in the stack trace below:
22:11:40.139 [main] DEBUG org.kie.server.client.impl.AbstractKieServicesClientImpl - About to deserialize content:
'{
"type" : "SUCCESS",
"msg" : "Kie Server info",
"result" : {
"kie-server-info" : {
"id" : "kie-server-a017ffcb29dc",
"version" : "7.55.0.Final",
"name" : "kie-server-a017ffcb29dc",
"location" : "http://172.17.0.3:8080/kie-server/services/rest/server",
**"capabilities" : [ "KieServer", "BRM", "BPM", "CaseMgmt", "BPM-UI", "BRP", "DMN", "Swagger" ],**
"messages" : [ {
"severity" : "INFO",
"timestamp" : {
"java.util.Date" : 1623926563857
},
"content" : [ "Server KieServerInfo{serverId='kie-server-a017ffcb29dc', version='7.55.0.Final', name='kie-server-a017ffcb29dc', location='http://172.17.0.3:8080/kie-server/services/rest/server', capabilities=[KieServer, BRM, BPM, CaseMgmt, BPM-UI, BRP, DMN, Swagger]', messages=null', mode=DEVELOPMENT}started successfully at Thu Jun 17 10:42:43 UTC 2021" ]
} ],
"mode" : "DEVELOPMENT"
}
}
}'
Below is the response I got back:
22:11:41.515 [main] DEBUG org.kie.server.client.impl.AbstractKieServicesClientImpl - About to deserialize content:
'{
"type" : "SUCCESS",
"msg" : "Container ImportProducts_1.0.1-LATEST successfully called.",
"result" : {
"execution-results" : {
"results" : [ {
"value" : [{"com.test.importproducts.ImportProduct":{
"id" : "1",
"category" : "Grocery - Milk",
"status" : "OK",
"price" : 25.0
}},{"com.test.importproducts.ImportProduct":{
"id" : "2",
"category" : "Fashion - Trouser",
"status" : "NOT_OK",
"price" : 1300.0
}},{"com.test.importproducts.ImportProduct":{
"id" : "3",
"category" : "Grocery - Wheat",
"status" : "OK",
"price" : 425.0
}},{"com.test.importproducts.ImportProduct":{
"id" : "4",
"category" : "Grocery - Dairy Milk Chocolate",
"status" : "OK",
"price" : 100.0
}}],
"key" : "ImportProduct"
} ],
"facts" : [ {
"value" : {"org.drools.core.common.DefaultFactHandle":{
"external-form" : "0:3:459769708:-992461270:3:DEFAULT:NON_TRAIT:java.util.ArrayList"
}},
"key" : "ImportProduct"
} ]
}
}
}'
Please help.
I fixed the issue. Below is the working code:
private Command<?> prepareCommands(List<ImportProduct> facts, String sessionName, String outIdentifier) {
KieCommands commandsFactory = KieServices.Factory.get().getCommands();
List<Command> commands = facts.stream().map(commandsFactory::newInsert).collect(Collectors.toList());
commands.add(commandsFactory.newFireAllRules());
ObjectFilter factsFilter = new ClassObjectFilter(ImportProduct.class);
//System.out.println("Check1: "+commandsFactory.newGetObjects(factsFilter, CLASS_NAME));
//System.out.println("Check2: "+commands.toString());
commands.add(commandsFactory.newGetObjects(factsFilter, CLASS_NAME));
return commandsFactory.newBatchExecution(commands, sessionName);
}
According to the documentation, I'm trying to get a working name for a method of a Spring MongoRepository that have to meet two different conditions. In plain words, the query sounds like: "look up for a determinate object by his id and it is one of mine or I want to share it"
The object:
{
"_id" : ObjectId("5c497..."),
"owner" : "myUserId",
"shared" : false,
}
The query:
db.getCollection('collection').find({$or : [
{ $and : [ { '_id' : ObjectId("5c497...") }, { 'owner' : 'myUserId' } ] },
{ $and : [ { '_id' : ObjectId("5c497...") }, { 'shared' : true } ] }
]})
I solved the problem with #Query
#Query("{\$or: [{\$and: [{'_id' : ?0}, {'owner' : ?1}]}, {\$and: [{'_id' : ?0}, {'shared' : true}]} ]}")
fun findIfAvailable(id: ObjectId, owner: String, shared: Boolean = true): Mono<MyObj>
But now, I wondered if it's possible to writing a method name for simplify the code ( and learn how use it ).
I tried without success findByIdAndOwnerOrShared, findByIdAndOwnerOrIdAndShared and so on
Thank you
I am facing an issue with using different Spring Controllers.
We are using a standard Spring PagingAndSortingRepository annotated with RepositoryRestResource to serve search responses . One of the methods is
Page<Custodian> findByShortNameContainingIgnoreCase(#Param("shortName") String shortName, Pageable p);
It returns all entities of Custodian that satisfy the conditions grouped in Pages.
The result looks like this:
{
"_embedded" : {
"custodians" : [ {
"shortName" : "fr-custodian",
"name" : "french custodian",
"contact" : "Francoir",
"_links" : {
"self" : {
"href" : "http://127.0.0.1:9000/api/custodians/10004"
},
"custodian" : {
"href" : "http://127.0.0.1:9000/api/custodians/10004"
}
}
} ]
},
"_links" : {
"self" : {
"href" : "http://127.0.0.1:9000/api/custodians/search/findByShortNameContainingIgnoreCase?shortName=fr&page=0&size=3&sort=shortName,asc"
}
},
"page" : {
"size" : 3,
"totalElements" : 1,
"totalPages" : 1,
"number" : 0
}
}
This is the format our frontend expects.
However, we need another query that results in a pretty long function (and thus URL) because it takes multiple parameters.
To be specific, it globally searches for a string in Custodian. So every parameter has the same value.
In order to shorten the URL we created a RepositoryRestController annotated with ResponseBody and implemented a function that takes only one parameter, calls the long URL internally and re-returns the result (a Page).
#RequestMapping(value = "/custodian", method = RequestMethod.GET)
public Page<Custodian> search(#RequestParam(value = "keyWord") String keyWord, Pageable p) {
return repo.LONGURL(keyWord, keyWord, p);
}
Unfortunately, Spring doesn't apply the same format to the result of our function.
It looks like this:
{
"content" : [ {
"id" : 10004,
"shortName" : "fr-custodian",
"name" : "french custodian",
"contact" : "Francoir",
} ],
"pageable" : {
"sort" : {
"sorted" : true,
"unsorted" : false
},
"offset" : 0,
"pageSize" : 3,
"pageNumber" : 0,
"unpaged" : false,
"paged" : true
},
"totalElements" : 3,
"totalPages" : 1,
"last" : true,
"size" : 3,
"number" : 0,
"sort" : {
"sorted" : true,
"unsorted" : false
},
"numberOfElements" : 3,
"first" : true
}
How do you get Spring to deliver the same format in our custom method?
I'm looking for a parallel approach to solving a problem. One approach I posted in "How can I subract two json files in ruby." Another approach is this.
I'm using this nifty json_diff.rb program to compare two similarly-structured json files. How can I skip certain attributes that can be nested inside other attributes?
For example, I have file1.json
{
"id" : "file1",
"att1" : {
"attA" : {
"free_mem" : "1234",
"buff_mem" : "5678"
},
"attB" : {
"name" : "Joe",
"location" : "Lab"
}
}
}
and file2.json
{
"id" : "file2",
"att1" : {
"attA" : {
"free_mem" : "5555",
"buff_mem" : "6666"
},
"attB" : {
"name" : "John",
"location" : "Lab"
}
}
}
I want to ignore attA. Note that these files are just examples, and real json files I have will have more attributes to ignore, which may be nested deeper inside other attributes.
I've done this in rspec with json_spec: https://github.com/collectiveidea/json_spec with good success. but that's specific to rspec and not just ruby