[javascript] 키 이름의 MongoDB 점 (.)

mongo는 점 (.) 또는 달러 기호 ($)가있는 키 삽입을 허용하지 않는 것 같지만 mongoimport 도구를 사용하여 점이 포함 된 JSON 파일을 가져 오면 제대로 작동했습니다. 운전자가 해당 요소를 삽입하려는 것에 대해 불평하고 있습니다.

다음은 데이터베이스에서 문서의 모습입니다.

{
    "_id": {
        "$oid": "..."
    },
    "make": "saab",
    "models": {
        "9.7x": [
            2007,
            2008,
            2009,
            2010
        ]
    }
}

내가이 모든 일을 잘못하고 있고 외부 데이터 (예 : 모델)와 함께 해시 맵을 사용해서는 안됩니까? 아니면 어떻게 든 점을 이스케이프 할 수 있습니까? 어쩌면 나는 너무 많은 Javascript와 비슷하다고 생각하고 있습니다.



답변

MongoDB는 점이 있는 키를 지원하지 않으므로 가져 오기 전에 JSON 파일을 제거 / 교체하기 위해 사전 처리해야합니다. 그렇지 않으면 모든 종류의 문제에 대해 스스로 설정해야합니다.

이 문제에 대한 표준 해결 방법은 없으며 최상의 방법은 상황의 세부 사항에 너무 의존하는 것입니다. 하지만 가능한 한 모든 주요 인코더 / 디코더 접근 방식을 피하고 싶습니다. JSON 재구성은 아마도 일회성 비용이 될 수있는 불편 함을 영구적으로 지불 할 것이기 때문입니다.


답변

다른 답변에서 언급했듯이 MongoDB는 필드 이름대한 제한으로 인해 $또는 .문자를 맵 키로 허용하지 않습니다 . 그러나 달러 기호 연산자 에서 언급 했듯이이 제한 사항을 이스케이프 한다고해서 이러한 키가있는 문서 삽입 할 수있는 것은 아닙니다. 문서를 업데이트하거나 쿼리 할 수 ​​없습니다.

단순히 교체의 문제 .와 함께 [dot]U+FF0E(이 페이지에 다른 곳에서 언급 한 바와 같이이) 어떤 사용자가 합법적으로 키 저장하려고 할 때 발생한다 [dot]또는 U+FF0E?

Fantom의 afMorphia 드라이버 가 취하는 접근 방식 은 Java와 유사한 유니 코드 이스케이프 시퀀스를 사용하지만 이스케이프 문자가 먼저 이스케이프되도록하는 것입니다. 본질적으로 다음과 같은 문자열 대체가 이루어집니다 (*).

\  -->  \\
$  -->  \u0024
.  -->  \u002e

나중에 MongoDB 에서 맵 키를 읽을 때 역방향 교체가 수행됩니다 .

또는 Fantom 코드에서 :

Str encodeKey(Str key) {
    return key.replace("\\", "\\\\").replace("\$", "\\u0024").replace(".", "\\u002e")
}

Str decodeKey(Str key) {
    return key.replace("\\u002e", ".").replace("\\u0024", "\$").replace("\\\\", "\\")
}

사용자가 이러한 변환을 인식해야하는 유일한 시간은 해당 키에 대한 쿼리를 구성 할 때입니다.

dotted.property.names구성 목적으로 데이터베이스에 저장하는 것이 일반적이라는 점을 감안할 때 이러한 접근 방식이 모든 맵 키를 단순히 금지하는 것보다 낫다고 생각합니다.

(*) afMorphia는 실제로 Java의 유니 코드 이스케이프 구문에 언급 된대로 전체 / 적절한 유니 코드 이스케이프 규칙을 수행 하지만 설명 된 대체 시퀀스도 잘 작동합니다.


답변

몽고의 워드 프로세서 와 같은 잘못된 문자를 교체 할 것을 제안 $하고 .자신의 유니 코드 등가물.

이러한 상황에서 키는 예약 된 $ 및을 대체해야합니다. 문자. 모든 문자로 충분하지만 U + FF04 (예 : “$”) 및 U + FF0E (예 : “.”)와 같은 유니 코드 전체 너비를 사용하는 것이 좋습니다.


답변

MongoDB의 최신 안정 버전 (v3.6.1)은 현재 키 또는 필드 이름에 점 (.)을 지원합니다.

이제 필드 이름에 점 (.) 및 달러 ($) 문자가 포함될 수 있습니다.


답변

방금 구현 한 솔루션 중 정말 만족 스럽습니다. 키 이름과 값을 두 개의 개별 필드로 분할하는 것입니다. 이렇게하면 문자를 똑같이 유지할 수 있으며 구문 분석 악몽에 대해 걱정할 필요가 없습니다. 문서는 다음과 같습니다.

{
    ...
    keyName: "domain.com",
    keyValue: "unregistered",
    ...
}

keyName keyValuefind 필드 에서 a 를 수행하여 쉽게 쿼리 할 수 ​​있습니다 .

그래서 대신 :

 db.collection.find({"domain.com":"unregistered"})

실제로 예상대로 작동하지 않을 경우 다음을 실행합니다.

db.collection.find({keyName:"domain.com", keyValue:"unregistered"})

예상 된 문서를 반환합니다.


답변

값 대신 키에 해시를 사용한 다음 해당 값을 JSON 값에 저장할 수 있습니다.

var crypto = require("crypto");

function md5(value) {
    return crypto.createHash('md5').update( String(value) ).digest('hex');
}

var data = {
    "_id": {
        "$oid": "..."
    },
    "make": "saab",
    "models": {}
}

var version = "9.7x";

data.models[ md5(version) ] = {
    "version": version,
    "years" : [
        2007,
        2008,
        2009,
        2010
    ]
}

그런 다음 나중에 해시를 사용하여 모델에 액세스합니다.

var version = "9.7x";
collection.find( { _id : ...}, function(e, data ) {
    var models = data.models[ md5(version) ];
}


답변

지금 지원됩니다

MongoDb 3.6 이상 에서는 필드 이름에서 달러 를 모두 지원 합니다. JIRA 아래 참조 : https://jira.mongodb.org/browse/JAVA-2810

Mongodb를 3.6 이상으로 업그레이드하는 것이 가장 좋은 방법입니다.