I have this document:
{
"_id": ObjectId("xxx"),
"props": {
"a": "a1",
"b": "b2"
}
}
My query looks like this:
db.collection.find({"$and": [ {"props.a" : "a1"}, {"props.b": "b2"} ]}
I get the elements of the query from GET values:
/api/search?a=a1&b=b1
So, I need a way to generate dinamically my query starting from the GET object...
I thought about something like this:
// Little helper to get the object key name by index
Object.prototype.key = function key(int) { var j = -1; for(var i in this) { j++; if(j==int) { return i; } else { continue; } } }
// My attempt
var query = [],
i = 0;
_.each(req.query, function(prop) {
var key = req.query.key(i);
query.push({"props." + key: prop});
i = i + 1;
});
But it does not work...
if I do:
_.each(req.query, function(prop) {
var key = {};
key.properties = {};
key.properties[req.query.key(i)] = prop ;
props.push(key);
i = i + 1;
});
I get this:
[{ props: { a: 'a1' } }, { props: { b: 'b1' } } ]
but in this way I could get only this query:
db.collection.find({"$and": [ { props: { a: 'a1' } }, { props: { b: 'b1' } } ]}
which is completely different from the one I've written above (this one search for a props which is exactly like the ones I've provided, instead the original looks for one which contains one of the values)
how can I do?
Ok I've found a solution, searching on google did not returned any solutions...
var query = {"$and": []},
props = [],
i = 0;
_.each(req.query, function(prop) {
var key = {};
key["properties." + req.query.key(i)] = prop ;
props.push(key);
i = i + 1;
});
query.$and = props;
In this way the query generated is exactly like I need it.
Related
I am a coding beginner and I am building a store. My problem is that I have a product in different fabrics. Now I can only select one fabric type and the other is disabled and I can not select no matter what I do. Perfect would be if I select the fabric type, the associated products are displayed.
That what i mean
/*============================================================================
Dynamic variant availability
- To disable, set dynamicVariantsEnable to false in theme.liquid
==============================================================================*/
setCurrentVariantAvailability: function(variant) {
var valuesToEnable = {
option1: [],
option2: [],
option3: []
};
// Disable all options to start
this.disableVariantGroup($(selectors.formContainer, this.$container).find('.variant-input-wrap'));
// Combine all available variants
var availableVariants = this.variantsObject.filter(function(el) {
if (variant.id === el.id) {
return false;
}
// Option 1
if (variant.option2 === el.option2 && variant.option3 === el.option3) {
return true;
}
// Option 2
if (variant.option1 === el.option1 && variant.option3 === el.option3) {
return true;
}
// Option 3
if (variant.option1 === el.option1 && variant.option2 === el.option2) {
return true;
}
});
// IE11 can't handle shortform of {variant} so extra step is needed
var variantObject = {
variant: variant
};
availableVariants = Object.assign({}, variantObject, availableVariants);
// Loop through each available variant to gather variant values
for (var property in availableVariants) {
if (availableVariants.hasOwnProperty(property)) {
var item = availableVariants[property];
var option1 = item.option1;
var option2 = item.option2;
var option3 = item.option3;
if (option1) {
if (valuesToEnable.option1.indexOf(option1) === -1) {
valuesToEnable.option1.push(option1);
}
}
if (option2) {
if (valuesToEnable.option2.indexOf(option2) === -1) {
valuesToEnable.option2.push(option2);
}
}
if (option3) {
if (valuesToEnable.option3.indexOf(option3) === -1) {
valuesToEnable.option3.push(option3);
}
}
}
}
// Have values to enable, separated by option index
if (valuesToEnable.option1.length) {
this.enableVariantOptionByValue(valuesToEnable.option1, 'option1');
}
if (valuesToEnable.option2.length) {
this.enableVariantOptionByValue(valuesToEnable.option2, 'option2');
}
if (valuesToEnable.option3.length) {
this.enableVariantOptionByValue(valuesToEnable.option3, 'option3');
}
},
updateVariantAvailability: function(evt, value, index) {
if (value && index) {
var newVal = value;
var optionIndex = index;
} else {
var $el = $(evt.currentTarget);
var newVal = $el.val() ? $el.val() : evt.currentTarget.value;
var optionIndex = $el.data('index');
}
var variants = this.variantsObject.filter(function(el) {
return el[optionIndex] === newVal;
});
// Disable all buttons/dropdown options that aren't the current index
$(selectors.formContainer, this.$container).find('.variant-input-wrap').each(function(index, el) {
var $group = $(el);
var currentOptionIndex = $group.data('index');
if (currentOptionIndex !== optionIndex) {
// Disable all options as a starting point
this.disableVariantGroup($group);
// Loop through legit available options and enable
for (var i = 0; i < variants.length; i++) {
this.enableVariantOption($group, variants[i][currentOptionIndex]);
}
}
}.bind(this));
},
disableVariantGroup: function($group) {
if (this.settings.variantType === 'dropdown') {
$group.find('option').prop('disabled', true)
} else {
$group.find('input').prop('disabled', true);
$group.find('label').toggleClass('disabled', true);
}
},
enableVariantOptionByValue: function(array, index) {
var $group = $(selectors.formContainer, this.$container).find('.variant-input-wrap[data-index="'+ index +'"]');
for (var i = 0; i < array.length; i++) {
this.enableVariantOption($group, array[i]);
}
},
enableVariantOption: function($group, value) {
// Selecting by value so escape it
value = value.replace(/([ #;&,.+*~\':"!^$[\]()=>|\/#])/g,'\\$1');
if (this.settings.variantType === 'dropdown') {
$group.find('option[value="'+ value +'"]').prop('disabled', false);
} else {
var $buttonGroup = $group.find('.variant-input[data-value="'+ value +'"]');
$buttonGroup.find('input').prop('disabled', false);
$buttonGroup.find('label').toggleClass('disabled', false);
}
},
Have already tried various things, but not come to the desired result, even disabling the function ensures that everything is displayed and also clickable.
I hope you can help me.
Best Regards
Let's say I have this very basic search
const from = 'something';
const to = 'somethingElse';
const firstSearchCondition = { from, to: 'test' };
const secondSearchCondition = { from: 'test', to };
const models = await Model.findAll({
where: {
[Op.or]: [
firstSearchCondition,
secondSearchCondition
],
},
});
const [toTest, fromTest] = models;
if (toTest && fromTest) {
// both models exist
}
when both models exist, is toTest 100% from firstSearchCondition? or the order is not guaranteed
Order is not guaranteed unless you use an order by clause. Regardless of the query.
Thanks to #Lev and some more researches on my side, what I've come up as solution is something like this:
hope it helps future people ( if you have any idea to make it better, hit me up )
let toTest = null;
let fromTest = null;
for (let i = 0; i < models.length; i += 1) {
if (models[i].to === 'test') {
toTest = models[i];
} else {
fromTest = models[i];
}
}
// check here if both exist
Im making a game and one of its functions is to join/create private rooms. Private rooms are generated randomly, but before generating a room, I want to try to be sure that the room id don't exists.
var rooms = {
'ROOM ID GENERATED RANDOMLY':
Room {
id: 'ROOM ID GENERATED RANDOMLY',
players: [],
gameState: 'WAITING',
currentCard: 'g:2',
currentPlayerIndex: NaN,
currentDirection: 1,
cardsStack: [] },
'ROOM ID GENERATED RANDOMLY':
Room {
id: 'ROOM ID GENERATED RANDOMLY',
players: [ [Player] ],
gameState: 'WAITING',
currentCard: 'g:2',
currentPlayerIndex: 0,
currentDirection: 1,
cardsStack: [] },
...
}
Already tried
var SEARCH = 'x';
for (var i=0; i < rooms.length; i++) {
console.log(rooms[i])
if (rooms[i].Room.id === SEARCH) {
return rooms[i];
}
}
Try this function
function roomIdIsUnique (newKey) {
var roomKeys = Object.keys(rooms);
for (const key of roomKeys) {
if (key === newKey) return false;
}
return true;
}
var rooms = { /* Room objects */ }
var newRoomKey = /* Generate new room key code */
if (roomIdIsUnique(newRoomKey)) {
/* Continue */
} else {
/* Do something else */
}
This question is pretty vague, but I'll do my best to answer it.
You can use Object.keys() to get an array containing the keys, and then run the Array#indexOf function on that array. It will return -1 if the key is not in the array, else it will return the index
var rooms = { "key1": { property: "123" }, "key2": { property: "abc" } }
if(Object.keys(rooms).indexOf(SEARCH) != -1) {
alert("Room id exists");
} else {
alert("Room does not exist");
}
Here, I am fetching a data from the user. The first line contains an integer, denoting the number of entries in the phone book.
Each of the subsequent lines describes an entry in the form of space-separated values on a single line. The first value is a friend's name, and the second value is a digit phone number.
For example:
2
sam 99912222
tom 11122222
So, while processing this input, I am taking the number of entries from the user and assigning it to variable noOfIterations. For the subsequent entries, I am assigning it to a list of objects wherein the format will be : for eg. [{ sam: '99912222' },{ tom: '11122222' }].
But the problem is I get [ 'sam 99912222', 'tom 11122222' ] instead while consoling the map variable. Why do I get this?
function processData(input) {
var noOfIterations = 0;
var map = input.split('\n').filter(function (string, index){
if(index===0){
noOfIterations = parseInt(string);
}
else{
var splitStrings = string.trim().split(' ');
var obj = {};
obj[splitStrings[0]] = splitStrings[1];
console.log(obj);
return obj;
}
});
console.log(map);
}
process.stdin.resume();
process.stdin.setEncoding("ascii");
_input = "";
process.stdin.on("data", function (input) {
_input += input;
});
process.stdin.on("end", function () {
processData(_input);
});
You need to use map instead of filter to transform the input data.
function processPhoneBook(input) {
var result = input.split('\n')
.filter(function(line, index) { return index > 0 })
.map(function(line) {
var splitLine = line.trim().split(' ');
return {[splitLine[0]]: splitLine[1]};
});
console.log(result);
}
Example:
processPhoneBook("3\nana 1\npep 2") outputs [ { ana: '1' }, { pep: '2' } ]
I've removed noOfIterations var since you weren't using it. If you need to use it for further processing, you can filter the result after the mapping phase:
function processPhoneBook(input) {
var noOfIterations = 0;
var result = input.split('\n')
.map(function(line, index) {
if (index === 0) {
noOfIterations = parseInt(line);
return null;
}
var splitLine = line.trim().split(' ');
return {[splitLine[0]]: splitLine[1]};
})
.filter(function(line) { return line != null })
console.log(result);
}
I have a question regarding parse cloud code. The following cloud code was working before migration written in cloud code but after migration its not returning desired output.
var streamClass = Parse.Object.extend("Streams");
streamObj = new streamClass({
objectId: "dummy",
streamerId: usersArr[i]
});
streamObj.dirty = function() {return false;};
There are two entities i.e. streams and users. Every user has streams. So there is users pointer(streamerId) in stream table. If user do not have any stream created then i am creating a stream dummy object and setting user(streamerId) as a pointer in stream object. When this code was called as a API, it was returning stream dummy object with user(streamerId) information before parse server migration. After migration the above code gives the following output.
{
"result": [
{
"__type": "Pointer",
"className": "Streams",
"objectId": "dummy"
}
]
}
It can noticed that there is no user(streamerId) information in the output. Can anyone please help me in this regard.
I am not saving this streamObj. I am returning this streamObj to IOS app. I also tested it through postman in google chrome. The following is a complete function which takes array of users object and array of streams objects and return one object contains user and its related streams.
function getUsersAndRecentStreams(usersArr, streamsArr) {
var responseObj = [];
var moment = require('moment');
var now = moment();
var currentDate = new Date();
for( var i=0; i<usersArr.length; i++ ) {
var streamObj = null;
for( j=0; j<streamsArr.length; j++ ) {
var streamerObj = streamsArr[j].get('streamerId');
if( streamerObj.id === usersArr[i].id ) {
if( moment(streamsArr[j].get('showTimeStart')) <= now && moment(streamsArr[j].get('showTimeEnd')) >= now ) {
streamObj = streamsArr[j];
break;
}
if( streamObj == null) {
streamObj = streamsArr[j];
}
else {
if( moment(streamsArr[j].get('showTimeStart')) <= now ) {
streamObj = streamsArr[j];
}
}
}
}
if( streamObj == null ) {
var streamClass = Parse.Object.extend("Streams");
streamObj = new streamClass({
objectId: "dummy",
streamerId: usersArr[i]
});
streamObj.dirty = function() {return false;};
var streamObj = new streamObj();
}
responseObj.push(streamObj);
}
return responseObj;
}
There are two cases.
1) When streamObj is not null. In this case the output is correct.
2) The second case when streamObj is null. In this case the following output is return which is not desired.
{
"result": [
{
"__type": "Pointer",
"className": "Streams",
"objectId": "dummy"
}
]
}
When streamObj is null, The following desired output should return this function.
{
"result": [
{
"__type": "Pointer",
"className": "Streams",
"objectId": "dummy",
"StreamerId": userObject
}
]
}