문제

특정 종류의 무작위 레코드를 반환하는 GQL 쿼리를 작성하려고합니다. 내 현재 구현은 작동하지만 N 호출이 DataStore에 필요합니다. 가능하면 데이터 스토어로 전화를 걸고 싶습니다.

나는 현재 데이터 스토어에 넣는 모든 종류에 임의의 숫자를 할당합니다. 임의의 레코드를 쿼리 할 때 ASC Limit 1에 의해 다른 임의의 숫자와 레코드> rand 주문에 대한 쿼리를 생성합니다.

그러나 이것은 작동하지만 1 레코드 만 반환하므로 쿼리를 수행해야합니다. 이 쿼리를 만드는 방법에 대한 아이디어가 있습니까? 감사.

도움이 되었습니까?

해결책

"후드 아래"단일 검색 쿼리 호출은 일부 인덱스에서 연속 행을 반환 할 수 있습니다. 그렇기 때문에! =의 사용을 포함한 일부 GQL 쿼리가 여러 데이터 스토어 호출로 확장되는 이유입니다.

n 독립적 인 균일 랜덤 선택은 (일반적으로) 어떤 색인에서도 연속적이지 않습니다.

Qed.

Memcache를 사용하여 엔티티를 저장하고 N을 잡는 비용을 줄일 수 있습니다. 또는 인덱스에서 "랜덤"선택이 서로 가까운 것을 신경 쓰지 않으면 하나의 쿼리에서 무작위로 선택된 (say) 100의 블록을 선택한 다음 그 중 무작위로 n을 선택하십시오. 이미 무작위 화 된 필드가 있으므로 N 항목이 관련되어 있음을 외부인에게는 즉시 분명하지 않습니다. 적어도, 그들은 많은 샘플을보고 항목 A와 Z가 무작위 인덱스에서 100 개 이상 떨어져 있기 때문에 같은 그룹에 나타나지 않는다는 것을 알지 못합니다. 성능이 허용되면 때때로 엔티티를 다시 랜치화할 수 있습니다.

다른 팁

어떤 종류의 트레이드 오프를 찾고 있습니까? 이러한 엔티티를 삽입하는 데 작은 성능을 얻을 의향이 있다면 N을 매우 빠르게 얻을 수있는 솔루션을 만들 수 있습니다.

다음은해야 할 일입니다.

엔티티를 삽입 할 때 키를 지정하십시오. 1부터 시작하여 그곳에서 올라가는 순서대로 엔터티에 열쇠를주고 싶습니다. (App Engine은 AutoinCrement ()가 없으므로 약간의 노력이 필요하므로 다른 엔티티에서 사용한 마지막 ID를 추적해야합니다. Idgenerator라고 부릅니다).

이제 N 랜덤 엔티티가 필요할 때 1과 마지막 ID가 무엇이든 N Random Number를 생성하십시오 (Idgenerator는 이것을 알게 될 것입니다). 그런 다음 N 키를 사용하여 키에 의해 배치를 얻을 수 있습니다. N 키는 데이터 스토어로 한 번만 여행하면 쿼리보다 빠릅니다. 키가 일반적으로 쿼리보다 빠르기 때문에 쿼리보다 빠릅니다.

이 방법은 몇 가지 성가신 세부 사항을 다루어야합니다.

  1. 이 품목을 즉석에 삽입하는 경우 (초 1 초 이상) Idgenerator가 병목 현상이 될 수 있습니다. 이 모든 데이터가 사전로드되거나 볼륨이 적지 않으면 쉽게 쉽습니다.
  2. 일부 ID에는 실제로 ID와 관련된 엔티티가 없다는 것을 알 수 있습니다. 왜냐하면 삭제했거나 put ()가 어딘가에 실패했기 때문입니다. 이런 일이 발생하면 다른 임의의 엔티티를 잡아야합니다. (당신이 공상을 얻고 이것의 확률을 줄이고 싶다면,이 ID가 Idgenerator에서 "구멍을 채우기"를 재사용 할 수 있도록 할 수 있습니다)

따라서 문제는 이러한 N 항목이 얼마나 빨리 필요한지와 얼마나 자주 추가하고 삭제할 것인지, 그리고 약간의 추가 복잡성이 그 성능 향상의 가치가 있는지 여부에 달려 있습니다.

유일한 방법은 각 엔티티의 특수 속성에 임의의 정수 값을 저장하고 이에 대한 쿼리입니다. 자동으로 초기화 된 속성을 추가하면 자동으로 수행 할 수 있습니다.

불행히도 데이터 스토어가 이미 채워진 경우 모든 엔티티의 처리가 필요합니다.

이상해, 알아

스티브의 답변에 동의합니다. 한 쿼리에서 무작위 행을 검색하는 방법은 없습니다.

그러나, 하나의 단일 엔티티를 검색하는 방법조차도 일반적으로 반환 된 결과의 prbability가 균등하게 분포되도록 작동하지 않습니다. 주어진 엔티티를 반환 할 확률은 무작위로 지정된 숫자의 간격과 다음 높은 임의 숫자에 따라 다릅니다. 예를 들어 임의 숫자 1,2 및 10이 할당 된 경우 (3-9 숫자 중 어느 것도 없음) 알고리즘은 "1"보다 "2"8 배 더 자주 반환됩니다.

나는 이것을 약간 더 많은 expensice 방식으로 수정했습니다. 누군가 관심이 있다면 공유하게되어 기쁩니다

난 그냥 같은 문제가있었습니다. 나는 이미 기존의 기존 항목에 ID를 할당하지 않기로 결정했고, 이미 샤드 카운터에서 TotalCount를 가지고 있었기 때문에 이것을했습니다.

이것은 "TotalCount"항목에서 "count"항목을 선택합니다. 열쇠.

    # select $count from the complete set
    numberlist = random.sample(range(0,totalcount),count)
    numberlist.sort()

    pagesize=1000

    #initbuckets
    buckets = [ [] for i in xrange(int(max(numberlist)/pagesize)+1) ]
    for k in numberlist:
        thisb = int(k/pagesize)
        buckets[thisb].append(k-(thisb*pagesize))
    logging.debug("Numbers: %s. Buckets %s",numberlist,buckets)

    #page through results.

    result = []
    baseq =  db.Query(MyEntries,keys_only=True).order("__key__")
    for b,l in enumerate(buckets):
        if len(l) > 0: 
            result += [ wq.fetch(limit=1,offset=e)[0] for e in l ]

        if b < len(buckets)-1: # not the last bucket
            lastkey  = wq.fetch(1,pagesize-1)[0]
            wq = baseq.filter("__key__ >",lastkey)

이것이 나에게 다소 복잡하다는 것을 조심스럽게 생각하며, 나는 여전히 나오지 않거나 X 오류가 없다는 것을 유죄 판결하지 않습니다.

그리고 Count가 TotalCount에 가까운 경우 이것은 매우 비쌀 수 있습니다. 그리고 수백만 행에서는 Appengine Time 경계 내에서 할 수 없을 수도 있습니다.

내가 올바르게 이해하면 n 랜덤 인스턴스를 검색해야합니다.

그것은 간단합니다. 키만 쿼리하기 만하면됩니다. 그리고 그렇게 random.choice 열 키의 결과는 키의 결과입니다. 그런 다음 키를 가져와 결과를 얻습니다.

keys = MyModel.all(keys_only=True)

n = 5 # 5 random instance

all_keys = list(keys)
result_keys = []

for _ in range(0,n) 
    key = random.choice(all_keys)
    all_keys.remove(key)
    result_keys.append(key)

# result_keys now contain 5 random keys.
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top