Лучший способ сделать это - использовать структуру агрегации для вычисления нашего нового поля.
Наиболее эффективное решение в MongoDB 3.4 с помощью $addFields
и $out
операторов конвейерной агрегации.
db.collection.aggregate(
[
{ "$addFields": {
"name": { "$concat": [ "$firstName", " ", "$lastName" ] }
}},
{ "$out": "collection" }
]
)
Обратите внимание, что это не обновляет вашу коллекцию, а вместо этого заменяет существующую коллекцию или создает новый. Также для операций обновления, для которых требуется «литье типов», вам потребуется обработка на стороне клиента, и в зависимости от операции вам может понадобиться использовать метод find()
вместо метода .aggreate()
.
. Мы делаем это с помощью $project
наших документов и используем оператор агрегации строк $concat
для возврата конкатенированной строки , we Оттуда вы затем перебираете курсор и используете оператор обновления $set
, чтобы добавить новое поле в ваши документы, используя массовые операции для максимальная эффективность.
var cursor = db.collection.aggregate([
{ "$project": {
"name": { "$concat": [ "$firstName", " ", "$lastName" ] }
}}
])
из этого, вам нужно использовать bulkWrite
.
var requests = [];
cursor.forEach(document => {
requests.push( {
'updateOne': {
'filter': { '_id': document._id },
'update': { '$set': { 'name': document.name } }
}
});
if (requests.length === 500) {
//Execute per 500 operations and re-init
db.collection.bulkWrite(requests);
requests = [];
}
});
if(requests.length > 0) {
db.collection.bulkWrite(requests);
}
В этой версии вам необходимо использовать устаревший API Bulk
и его связанные методы .
var bulk = db.collection.initializeUnorderedBulkOp();
var count = 0;
cursor.snapshot().forEach(function(document) {
bulk.find({ '_id': document._id }).updateOne( {
'$set': { 'name': document.name }
});
count++;
if(count%500 === 0) {
// Excecute per 500 operations and re-init
bulk.execute();
bulk = db.collection.initializeUnorderedBulkOp();
}
})
// clean up queues
if(count > 0) {
bulk.execute();
}
cursor["result"].forEach(function(document) {
db.collection.update(
{ "_id": document._id },
{ "$set": { "name": document.name } }
);
})
вызвать функцию addArray из функции DoStuff и передать ей numArray в качестве параметра
function DoStuff() {
let numArray;
let sumArray;
let start = 1;
let end = 5;
if (start > end){
alert("Error: first int greater than last!")
}
else {
let arraySize = end - start;
numArray = [start];
for (let x = start + 1; x <= end; ++x){
numArray.push(x);
}
}
addArray(numArray)
}
function addArray(numArray){
console.log(numArray);
}
все значения внутри функции являются локальными для этой функции ... если я не использую return
blockquote>Что ж, это ... частично верно. Первая часть верна, и нет «если». Оператор
return
просто указывает на значение, которое, в общем-то, возвращает функция. Это не значит, что эта переменная теперь глобальная. Значение вreturn
является своего рода «значением функции», и вы должны сохранить его в переменной, если хотите использовать его позже, как вы можете видеть в ответах других.
В вашем основном js-файле, который содержит эти функции onclick, у вас должна быть глобальная переменная для хранения вашего numArray после вызова функции doStuff.
Примерно так:
let globalNumArray
// on click button doStuff
function (){
globalNumArray = doStuff()
}
// on click button addArray
function() {
addArray(globalNumArray)
}
Мой большой вопрос - когда я возвращаю numArray ... куда девается это значение?
blockquote>Возвращаемое значение туда, где вы вызвали эту конкретную функцию.
Редактировать: Причина, по которой глобальные переменные не поощряются в js, заключается в том, что весь код имеет одно глобальное пространство имен, где javascript автоматически подразумевает глобальные переменные (например, переменные, которые явно не объявлены в локальной области видимости, являются автоматически добавляется в глобальное пространство имен). Полагая слишком много на глобальные переменные , можно привести к некоторым конфликтам между скриптами на одной странице. Это не значит, что вы не должны использовать глобальные переменные, но вы не должны использовать их легкомысленно. Если вам нужно, чтобы переменная была доступна после завершения функции, ваш выбор ограничен, поэтому либо используйте глобальную переменную, либо передайте переменную той функции, в которой вы нуждаетесь.
Вам просто нужно сохранить результат doStuff и затем получить доступ к этой переменной в addArray:
var result
function doStuff() {
//document.write("We are testing document writing now!");
let numArray;
let sumArray;
let start = parseInt(prompt("Enter a small number"));
let end = parseInt(prompt("Enter a larger number"));
if (start > end) {
alert("Error: first int greater than last!")
} else {
let arraySize = end - start;
numArray = [start];
for (let x = start + 1; x <= end; ++x) {
numArray.push(x);
}
result = numArray; // save result for later (has to be a global scope)
}
}
function addArray() { // you defined this without an input in your form, so stick to that
if (result) // check if value exists
console.log(result);
else
console.log("Please enter the numbers boundaries first first.");
}
<form>
<input type="button" value="Click Me to generate an array of numbers!" onclick="doStuff()" />
<input type="button" value="Click me to add the array numbers" onclick="addArray()" />
</form>
doStuff () возвращает значение, поэтому используйте возврат этой функции в качестве переменной. Мы можем присвоить это возвращаемое значение другой переменной или использовать непосредственно в выражении. Поэтому вызовите dostuff (), чтобы получить возвращаемое значение.
function doStuff(){
//document.write("We are testing document writing now!");
let numArray;
let sumArray;
let start = parseInt(prompt("Enter a small number"));
let end = parseInt(prompt("Enter a larger number"));
if (start > end){
alert("Error: first int greater than last!")
} else {
let arraySize = end - start;
numArray = [start];
for (let x = start + 1; x <= end; ++x){
numArray.push(x);
}
console.log(numArray);
return numArray;
}
}
console.log('HERE IS ARRAY: '+doStuff());
Вот пара вещей, которые, я думаю, могли бы вам помочь:
1) Разделить ваш код. doStuff запрашивает ввод данных у пользователя, но также генерирует массив, содержащий значения из min-max. У вас должна быть отдельная функция, которая генерирует массив от мин до макс. Разделив его, вы сможете легче идентифицировать проблему.
2) Несколько решений предлагают глобальную переменную, которая может быть опасной. Когда вы должны совместно использовать состояние, ограничьте его область действия только тем, что необходимо для доступа к этому состоянию.
3) Сделайте ваши интерфейсы согласованными. Вы не должны возвращать значение одного экземпляра и ничего в другом. Если есть ошибка, убедитесь, что вы согласны с тем, как вы уведомляете звонящего.
function buildArray(start, end) {
let arr = [];
if (start > end) {
// There are a lot ways to deal with this
// But you want a consistent interface for letting
// the caller no that start < end
throw {
message: 'Start can\'t be bigger than end',
};
}
for (let x = start; x <= end; x++) {
arr.push(x);
}
return arr;
}
// encapsulate the variable numArray, so that it is only accessible
// to the methods that need it
var numArrayModule = (function(){
let numArray = [];
return {
doStuff: function(){
let start = parseInt(prompt("Enter a small number"));
let end = parseInt(prompt("Enter a larger number"));
try {
numArray = buildArray(start, end);
} catch(err) {
console.log(err);
}
},
addArray: function(){
console.log(numArray);
},
}
}());
// You may use these as onClick handlers as well.
numArrayModule.doStuff();
numArrayModule.addArray();