mongoDb에서 인덱스로 배열 요소를 제거하는 방법
{
"_id" : ObjectId("4d1cb5de451600000000497a"),
"name" : "dannie",
"interests" : [
"guitar",
"programming",
"gadgets",
"reading"
]
}
위의 예에서 위 문서가 db.people 컬렉션 에 있다고 가정합니다 . 인덱스로 관심사 배열 의 세 번째 요소를 제거하는 방법은 무엇입니까?
편집하다:
이것이 내 현재 솔루션입니다.
var interests = db.people.findOne({"name":"dannie"}).interests;
interests.splice(2,1)
db.people.update({"name":"dannie"}, {"$set" : {"interests" : interests}});
더 직접적인 방법이 있습니까?
배열 인덱스로 당기거나 제거하는 직접적인 방법은 없습니다. 실제로 이것은 공개 된 문제입니다 http://jira.mongodb.org/browse/SERVER-1014 , 투표 할 수 있습니다.
해결 방법은 $ unset을 사용한 다음 $ pull을 사용하는 것입니다.
db.lists.update({}, {$unset : {"interests.3" : 1 }})
db.lists.update({}, {$pull : {"interests" : null}})
업데이트 : 일부 주석에서 언급했듯이이 접근 방식은 원자 적이 지 않으며 다른 클라이언트가 두 작업간에 읽고 / 또는 쓰는 경우 일부 경합 상태가 발생할 수 있습니다. 작업이 원자 적이어야하는 경우 다음을 수행 할 수 있습니다.
- 데이터베이스에서 문서 읽기
- 문서를 업데이트하고 배열에서 항목 제거
- 데이터베이스의 문서를 바꿉니다. 문서를 읽은 후 변경되지 않았는지 확인하기 위해 현재 패턴 이 mongo 문서에 설명 된 경우 업데이트를 사용할 수 있습니다.
연산 $pull
수정자를 사용 update
하여 배열에서 특정 요소를 제거 할 수 있습니다 . 제공 한 경우 쿼리는 다음과 같습니다.
db.people.update({"name":"dannie"}, {'$pull': {"interests": "guitar"}})
또한 $pullAll
모든 발생을 제거하기 위해 를 사용할 수도 있습니다 . 이에 대한 자세한 내용은 공식 문서 페이지-http: //www.mongodb.org/display/DOCS/Updating#Updating-%24pull
이것은 요소를 제거하기위한 기준으로 색인을 사용하지 않지만 유사한 경우에 도움이 될 수 있습니다. IMO, 배열 내부의 요소 주소 지정을 위해 인덱스를 사용하는 것은 mongodb가 내가 아는 것처럼 요소 순서에서 일관성이 없기 때문에 매우 신뢰할 수 없습니다.
GUID (ObjectID를 사용하는 경향이 있음) 필드 또는 배열의 각 하위 문서에 대해 자동 증가 필드를 사용하는 것이 좋습니다.
이 GUID를 사용하면 $ pull을 쉽게 실행할 수 있으며 올바른 GUID를 가져올 수 있습니다. 다른 어레이 작업도 마찬가지입니다.
설정되지 않은 답변을 사용하는 대신 필드를 고유 한 값 (즉, NULL이 아님)으로 설정 한 다음 즉시 해당 값을 가져 와서이 문제를 해결합니다. 비동기 관점에서 조금 더 안전합니다. 다음은 코드입니다.
var update = {};
var key = "ToBePulled_"+ new Date().toString();
update['feedback.'+index] = key;
Venues.update(venueId, {$set: update});
return Venues.update(venueId, {$pull: {feedback: key}});
Hopefully mongo will address this, perhaps by extending the $position modifier to support $pull as well as $push.
For people who are searching an answer using mongoose with nodejs. This is how I do it.
exports.deletePregunta = function (req, res) {
let codTest = req.params.tCodigo;
let indexPregunta = req.body.pregunta; // the index that come from frontend
let inPregunta = `tPreguntas.0.pregunta.${indexPregunta}`; // my field in my db
let inOpciones = `tPreguntas.0.opciones.${indexPregunta}`; // my other field in my db
let inTipo = `tPreguntas.0.tipo.${indexPregunta}`; // my other field in my db
Test.findOneAndUpdate({ tCodigo: codTest },
{
'$unset': {
[inPregunta]: 1, // put the field with []
[inOpciones]: 1,
[inTipo]: 1
}
}).then(()=>{
Test.findOneAndUpdate({ tCodigo: codTest }, {
'$pull': {
'tPreguntas.0.pregunta': null,
'tPreguntas.0.opciones': null,
'tPreguntas.0.tipo': null
}
}).then(testModificado => {
if (!testModificado) {
res.status(404).send({ accion: 'deletePregunta', message: 'No se ha podido borrar esa pregunta ' });
} else {
res.status(200).send({ accion: 'deletePregunta', message: 'Pregunta borrada correctamente' });
}
})}).catch(err => { res.status(500).send({ accion: 'deletePregunta', message: 'error en la base de datos ' + err }); });
}
I can rewrite this answer if it dont understand very well, but I think is okay.
Hope this help you, I lost a lot of time facing this issue.
Instead of using $pull we can use $pop for removing elements in an array by its index. But you should subtract 1 from index position for removing based on the index.
For E.g if you want to remove the element in index 0 you should use -1, for index 1 you should use 0 and so on...
Query To Remove 3rd Element(gadgets):
db.people.update({"name":"dannie"}, {'$pop': {"interests": 1}})
for reference: https://docs.mongodb.com/manual/reference/operator/update/pop/
'development' 카테고리의 다른 글
주기적인 iOS 백그라운드 위치 업데이트 (0) | 2020.09.05 |
---|---|
moment.js에서 변경 가능성을 어떻게 해결합니까? (0) | 2020.09.05 |
Start-Process로 표준 출력 및 오류 캡처 (0) | 2020.09.05 |
SQL Server 연결이 가끔 작동 함 (0) | 2020.09.05 |
Spring의 양식 태그에서 modelAttribute와 commandName 속성의 차이점은 무엇입니까? (0) | 2020.09.05 |